/**
 * This class embodies the Host authorization panel.
 */
package org.hackystat.ui.projectviewer.client;

import java.util.ArrayList;
import java.util.Date;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.WindowResizeListener;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;

/**
 * This class embodies the Host authorization panel.
 * @author David J. Nickles
 *
 */
public class HostStatusPanel extends HorizontalPanel implements WindowResizeListener {

  private Boolean rpcBusy;
  private Boolean firstcall;
  private Boolean dailyprojectdataStatus;
  private Boolean sensorbaseStatus;
  private Date sensorbaseTstamp;
  private Date dailyprojectdataTstamp;
  private Label sensorbaseHost;
  private Label sensorbaseFeedback;
  private Label dailyprojectdataHost;
  private Label dailyprojectdataFeedback;
  private Image sensorbaseHostImage;
  private Image dailyprojectdataHostImage;
  private Session session;
  
  /**
   * Construct a valid set of hosts.
   * 
   * @param session the current session attributes
   */
  public HostStatusPanel(Session session) {
    this.session = session;
    this.firstcall = Boolean.TRUE;
    this.rpcBusy = Boolean.FALSE;
    setStyleName(Styles.PANELSTYLE);
    this.setHorizontalAlignment(ALIGN_LEFT);
    
    VerticalPanel column1 = new VerticalPanel();
    column1.setHorizontalAlignment(ALIGN_CENTER);
    column1.setStyleName(Styles.HOSTPANELSTYLE);
    this.sensorbaseHostImage = new Image(Images.HOST_IMAGE);
    column1.add(this.sensorbaseHostImage);
    Label sensorbaseImageLabel = new Label("Sensorbase");
    sensorbaseImageLabel.setStyleName(Styles.SMALLLABELSTYLE);
    column1.add(sensorbaseImageLabel); 
    add(column1);
    
    VerticalPanel column2 = new VerticalPanel();
    column2.setHorizontalAlignment(ALIGN_CENTER);
    column2.setStyleName(Styles.HOSTPANELSTYLE);
    this.dailyprojectdataHostImage = new Image(Images.HOST_IMAGE);
    column2.add(this.dailyprojectdataHostImage);
    Label dpdImageLabel = new Label("DailyProjectData");
    dpdImageLabel.setStyleName(Styles.SMALLLABELSTYLE);
    column2.add(dpdImageLabel); 
    add(column2);
    
    VerticalPanel column3 = new VerticalPanel();
    column3.setVerticalAlignment(ALIGN_MIDDLE);
    HorizontalPanel col2row1 = new HorizontalPanel();
    Label sbPrefixLabel = new Label("Sensorbase URI:");
    sbPrefixLabel.setStyleName(Styles.URILABEL);
    col2row1.add(sbPrefixLabel);
    this.sensorbaseHost = new Label("default-uri");
    this.sensorbaseHost.setStyleName(Styles.URILABEL);
    col2row1.add(this.sensorbaseHost);
    column3.add(col2row1);
    this.sensorbaseFeedback = new Label("Sensorbase Feedback.");
    this.sensorbaseFeedback.setStyleName(Styles.EXAMPLELABELSTYLE);
    column3.add(this.sensorbaseFeedback);
    HorizontalPanel col2row2 = new HorizontalPanel();
    Label telPrefixLabel = new Label("DailyProjectData URI:");
    telPrefixLabel.setStyleName(Styles.URILABEL);
    col2row2.add(telPrefixLabel);
    this.dailyprojectdataHost = new Label("default-uri");
    this.dailyprojectdataHost.setStyleName(Styles.URILABEL);
    col2row2.add(this.dailyprojectdataHost);
    column3.add(col2row2);
    this.dailyprojectdataFeedback = new Label("DailyProjectData Feedback.");
    this.dailyprojectdataFeedback.setStyleName(Styles.EXAMPLELABELSTYLE);
    column3.add(this.dailyprojectdataFeedback);
    add(column3);
    Window.addWindowResizeListener(this);
    this.setWidth(Integer.toString(Window.getClientWidth() - 34) + Styles.PIXELSUFFIX);
    rpcGetHosts(); // NOPMD
  }
  
  /**
   * This method sets the name of the host uri.
   * @param uri the sensorbase host domain and path
   * 
   * @gwt.typeArgs uri <java.lang.String>
   */
  private final void setHosts(ArrayList uri) {
    if (uri != null) {
      this.rpcBusy = Boolean.FALSE;
      
      String dpdHostUri = (String)uri.get(0);
      if (dpdHostUri == null) {
        this.dailyprojectdataHost.setText("");
        this.session.setTelemetryHost("");
        this.dailyprojectdataHostImage.setUrl(Images.HOST_INVALID);
        this.dailyprojectdataFeedback.setText(
          "Property file does not contain a DailyProjectData host value.");
      }
      else {
        this.dailyprojectdataHost.setText(dpdHostUri);
        this.session.setTelemetryHost(dpdHostUri);
        this.dailyprojectdataHostImage.setUrl(Images.HOST_IMAGE);
        this.dailyprojectdataFeedback.setText("DailyProjectData host property value located.");
      }
      
      String sensorbaseHostUri = (String)uri.get(1);
      if (sensorbaseHostUri == null) {
        this.sensorbaseHost.setText("");
        this.session.setSensorbaseHost("");
        this.sensorbaseHostImage.setUrl(Images.HOST_INVALID);
        this.sensorbaseFeedback.setText("Property file does not contain sensorbase host value.");
      }
      else {
        this.sensorbaseHost.setText(sensorbaseHostUri);
        this.session.setSensorbaseHost(sensorbaseHostUri);
        this.sensorbaseHostImage.setUrl(Images.HOST_IMAGE);
        this.sensorbaseFeedback.setText("Sensorbase host property value located.");
      }
      
      if (this.firstcall.booleanValue()) {
        rpcIsTelemetryHost();
      }
    }
  }
  
  /**
   * Check with the servlet to get the host name from the properties file.
   */
  private final void rpcGetHosts() {
    if (!this.rpcBusy.booleanValue()) {
      this.rpcBusy = Boolean.TRUE;
      this.dailyprojectdataHostImage.setUrl(Images.WAIT_IMAGE);
      this.dailyprojectdataHostImage.setSize(Styles.IMAGESIZE, Styles.IMAGESIZE);
      this.sensorbaseHostImage.setUrl(Images.WAIT_IMAGE);
      this.sensorbaseHostImage.setSize(Styles.IMAGESIZE, Styles.IMAGESIZE);
      this.dailyprojectdataFeedback.setText("Searching for the dailyprojectdata properties file.");
      RPCServiceFactory.getInstance().getService().getHosts(new AsyncCallback()
      {
        public void onSuccess(Object result) {
          setHosts((ArrayList) result);
        }
    
        public void onFailure(Throwable caught) {
          if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
            CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, 
              "Cannot invoke get-properties on servlet.");
          } 
          else {
            CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, caught.toString());
          }
        }
      });
    }
  }
  
  /**
   * This method sets the state of the sensorbase service in the UI.
   * @param state Boolean represents the state of the user valid=true, invalid=false
   */
  public void setSensorbaseHostStatus(Boolean state) {
    this.sensorbaseHostImage.setUrl(Images.HOST_IMAGE);
    this.rpcBusy = Boolean.FALSE;
    this.sensorbaseTstamp = new Date();
    String time = DateTimeFactories.getInstance().getBodyfactory().format(this.sensorbaseTstamp);
    if (state != null && state.booleanValue()) {
      this.sensorbaseStatus = Boolean.TRUE;
      this.sensorbaseHostImage.setUrl(Images.HOST_VALID);
      this.sensorbaseFeedback.setText(time + ", Sensorbase service contacted successfully.");
      this.sensorbaseFeedback.setStyleName(Styles.VALIDLABELSTYLE);
      this.firstcall = Boolean.FALSE;
      this.session.getCompositeWidget().showUserPanel();
    } 
    else {
      this.sensorbaseStatus = Boolean.FALSE;
      this.sensorbaseHostImage.setUrl(Images.HOST_INVALID);
      this.sensorbaseFeedback.setText(time + ", Sensorbase service unavailable.");
      this.sensorbaseFeedback.setStyleName(Styles.INVALIDLABELSTYLE);
    }
  }
  
  /**
   * This method performs an RPC call to the servlet to check if the sensorbase service is up.
   */
  private void rpcIsSensorbaseHost() {
    if (!this.rpcBusy.booleanValue()) {
      this.rpcBusy = Boolean.TRUE;
      this.sensorbaseHostImage.setUrl(Images.WAIT_IMAGE);
      this.sensorbaseHostImage.setSize(Styles.IMAGESIZE, Styles.IMAGESIZE);
      RPCServiceFactory.getInstance().getService().isSensorBaseHost(this.sensorbaseHost.getText(),
        new AsyncCallback()
        {
          public void onSuccess(Object result) {
            setSensorbaseHostStatus((Boolean) result);
          }
      
          public void onFailure(Throwable caught) {
            if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
              CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, 
                "Cannot invoke host validation on servlet.");
            } 
            else {
              CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, caught.toString());
            }
          }
        });
    }
  }
  
  /**
   * This method sets the state of the dailyprojectdata service in the UI.
   * @param state Boolean represents the state of the user valid=true, invalid=false
   */
  public void setDPDHostStatus(Boolean state) {
    this.dailyprojectdataHostImage.setUrl(Images.HOST_IMAGE);
    this.rpcBusy = Boolean.FALSE;
    this.dailyprojectdataTstamp = new Date();
    String time = DateTimeFactories.getInstance().getBodyfactory().format(
      this.dailyprojectdataTstamp);
    if (state != null && state.booleanValue()) {
      this.dailyprojectdataStatus = Boolean.TRUE;
      this.dailyprojectdataHostImage.setUrl(Images.HOST_VALID);
      this.dailyprojectdataFeedback.setText(time 
        + ", DailyProjectData service contacted successfully.");
      this.dailyprojectdataFeedback.setStyleName(Styles.VALIDLABELSTYLE);
    } 
    else {
      this.dailyprojectdataStatus = Boolean.FALSE;
      this.dailyprojectdataHostImage.setUrl(Images.HOST_INVALID);
      this.dailyprojectdataFeedback.setText(time + ", DailyProjectData service unavailable.");
      this.dailyprojectdataFeedback.setStyleName(Styles.INVALIDLABELSTYLE);
    }
    if (this.firstcall.booleanValue()) {
      rpcIsSensorbaseHost();
    }
  }
  
  /**
   * This method performs an RPC call to the servlet to check if the dailyprojectdata service is up.
   */
  private void rpcIsTelemetryHost() {
    if (!this.rpcBusy.booleanValue()) {
      this.rpcBusy = Boolean.TRUE;
      this.dailyprojectdataHostImage.setUrl(Images.WAIT_IMAGE);
      this.dailyprojectdataHostImage.setSize(Styles.IMAGESIZE, Styles.IMAGESIZE);
      RPCServiceFactory.getInstance().getService().isDailyProjectDataHost(
        this.dailyprojectdataHost.getText(),
        new AsyncCallback()
        {
          public void onSuccess(Object result) {
            setDPDHostStatus((Boolean) result);
          }
      
          public void onFailure(Throwable caught) {
            if (caught instanceof com.google.gwt.user.client.rpc.InvocationException) {
              CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, 
                "Cannot invoke host validation on servlet.");
            } 
            else {
              CompositeWidget.log(RPCServiceFactory.PRCERRORNAME, caught.toString());
            }
          }
        });
    }
  }
  
  /**
   * This method returns if the sensorbase service is available.
   * @return true if the sensorbase service has been contacted successfully, false if not.
   */
  public Boolean getSensorbaseStatus() {
    return this.sensorbaseStatus;
  }
  
  /**
   * This method returns if the dailyprojectdata service is available.
   * @return true if the dailyprojectdata service has been contacted successfully, false if not.
   */
  public Boolean getTelemetryStatus() {
    return this.dailyprojectdataStatus;
  }
  
  /** 
   * Listens for user resizing of the window.
   * @param width of the adjusted window.
   * @param height of the adjusted window.
   */
  public void onWindowResized(int width, int height) {
    this.setWidth(Integer.toString(width - 34) + Styles.PIXELSUFFIX);
  }
}
